﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using SSE554_Proj1.Entity;

namespace SSE554_Proj1
{
    class ATS_Controller
    {
        static int progress = 0;

        private class SynchronizedController : ATS_Controller
        {
            private object syncRoot = new object();
            private ATS_Controller atsControl;

            public SynchronizedController(ATS_Controller atsCntrl)
            {
                this.atsControl = atsCntrl;
            }

            public override bool IsSynchronized
            {
                get { return true; }
            }
            public override void Online_Test(Instrument instUnderTest, ATS_Controller atsCntrl)
            {
                atsControl.Online_Test(instUnderTest, atsCntrl);
                lock (syncRoot)
                {
                    if (progress != 0)
                        Console.WriteLine("In-Progress {0}...", progress);
                }
            }

            public override Tuple<int, string> SelfTest(object characteristics)
            {
                Tuple<int, string> tup = atsControl.SelfTest(characteristics);
                lock (syncRoot)
                {
                    if (progress != 0)
                        Console.WriteLine("In-Progress {0}...", progress);
                }
                return tup;
            }
        }

        public virtual bool IsSynchronized
        {
            get { return false; }
        }

        public ATS_Controller Synchronized(ATS_Controller atsCntrl)
        {
            if (!atsCntrl.IsSynchronized)
            {
                return new SynchronizedController(atsCntrl);
            }
            return atsCntrl;
        }

        public virtual void Online_Test(Instrument instUnderTest, ATS_Controller atsCntrl)
        {
            try
            {
                //
                if (instUnderTest is Signal_Generator)
                {
                    if (instUnderTest.ModelName == "Tektronix")
                    {
                        progress++;
                        Console.WriteLine("ONLINE Check -----> " + instUnderTest.ToString() + " on {0}", DateTime.Now.ToLongTimeString());
                        Thread.Sleep(1000);
                        progress--;
                    }
                    else
                        throw new AggregateException(instUnderTest.ToString() + " Offline");
                }
                else if (instUnderTest is Oscilloscope){
                    if (instUnderTest.ModelName == "Agilent")
                    {
                        progress++;
                        Console.WriteLine("ONLINE Check -----> " + instUnderTest.ToString() + " on {0}", DateTime.Now.ToLongTimeString());
                        Thread.Sleep(1000);
                        progress--;
                    }
                    else
                        throw new AggregateException(instUnderTest.ToString() + " Offline");
                }
                else if (instUnderTest is Power_Supply)
                {
                    if (instUnderTest.ModelName == "Sorensen")
                    {
                        progress++;
                        Console.WriteLine("ONLINE Check -----> " + instUnderTest.ToString() + " on {0}", DateTime.Now.ToLongTimeString());
                        Thread.Sleep(1000);
                        progress--;
                    }
                    else
                        throw new AggregateException(instUnderTest.ToString() + " Offline");
                }
                else if (instUnderTest is Relays_Card)
                {
                    if (instUnderTest.ModelName == "VTITech")
                    {
                        progress++;
                        Console.WriteLine("ONLINE Check -----> " + instUnderTest.ToString() + " on {0}", DateTime.Now.ToLongTimeString());
                        Thread.Sleep(1000);
                        progress--;
                    }
                    else
                        throw new AggregateException(instUnderTest.ToString() + " Offline");
                }
                else if (instUnderTest is Multimeter)
                {
                    if (instUnderTest.ModelName == "Fluke")
                    {
                        progress++;
                        Console.WriteLine("ONLINE Check -----> " + instUnderTest.ToString() + " on {0}", DateTime.Now.ToLongTimeString());
                        Thread.Sleep(1000);
                        progress--;
                    }
                    else
                        throw new AggregateException(instUnderTest.ToString() + " Offline");
                }
                else if (instUnderTest is Digital_Module)
                {
                    //if (!atsCntrl.IsSynchronized) throw new UnsynchronizedException("Requires synchronization: " + instUnderTest.ToString());
                    if (instUnderTest.ModelName == "Teradyne")
                    {
                        progress++;
                        Console.WriteLine("ONLINE Check -----> " + instUnderTest.ToString() + " on {0}", DateTime.Now.ToLongTimeString());
                        Thread.Sleep(1000);
                        progress--;
                    }
                    else
                        throw new AggregateException(instUnderTest.ToString() + " Offline");
                }
                else
                    throw new AggregateException("Invalid Type");
            }
            catch (UnsynchronizedException ue)
            {
                //Console.WriteLine("{0}: {1}", ue.Message, instUnderTest.ModelName);
                throw;
            }
            catch (AggregateException aex)
            {
                Console.WriteLine(aex.Message);
            }
        }

        public virtual Tuple<int, string> SelfTest(object characteristics)
        {
            int runtime, result = 1;
            Random stResult = new Random();

            try
            {
                Instrument instUnderTest = (Instrument)characteristics;
                progress++;
                Console.WriteLine("SELFTEST Started -> " + instUnderTest.ToString() + " on {0}", DateTime.Now.ToLongTimeString());
                runtime = instUnderTest.STRuntime;
                Thread.Sleep(runtime);
                result = stResult.Next(2);
                progress--;
                if (result == 0)
                    Console.WriteLine("SELFTEST Passed <-- " + instUnderTest.ToString() + " on {0}\n", DateTime.Now.ToLongTimeString());
                else
                    Console.WriteLine("SELFTEST Failed <-- " + instUnderTest.ToString() + " on {0}\n", DateTime.Now.ToLongTimeString());
                return Tuple.Create<int, string>(result, "Replaced " + instUnderTest.ToString());
            }
            catch (UnsynchronizedException ue)
            {
                Console.WriteLine("{0}: {1}", ue.Message, "Tuple");
                //return null;
                return Tuple.Create<int, string>(1, "Not Run");
            }
        }
    }
}
